using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 标记当前类必须的组件，语法由Unity提供
[RequireComponent(
  typeof(Rigidbody2D),
  typeof(PhysicCheck),
  typeof(Animator)
)]
public class Enemy : MonoBehaviour
{
  Rigidbody2D rb;
  [HideInInspector] public PhysicCheck physicCheck;
  // protected 内部和子类可以访问
  [HideInInspector] public Animator anim;

  // Start is called before the first frame update
  [Header("基本参数")]
  public float normalSpeed;
  public float chaseSpeed;
  [HideInInspector] public float curSpeed;
  public float hurtForce;
  public Vector3 faceDir;
  public Transform attacker;

  [Header("检测")]
  public Vector2 centerOffset;
  public Vector2 checkSize;
  public float checkDistance;
  public LayerMask attackLayer;

  [Header("计时器")]
  public float waitTime;
  public float waitTimeCounter;
  public bool isWait;
  public float lostTime;
  public float lostTimeCounter;

  [Header("状态")]
  public bool isHurt;
  public bool isDead;
  protected BaseState patrolState;
  protected BaseState chaseState;
  protected BaseState skillState;
  private BaseState curState;

  #region 周期函数
  protected virtual void Awake()
  {
    rb = GetComponent<Rigidbody2D>();
    anim = GetComponent<Animator>();
    physicCheck = GetComponent<PhysicCheck>();

    curSpeed = normalSpeed;
    waitTimeCounter = waitTime;
  }

  /// <summary>
  /// This function is called when the object becomes enabled and active.
  /// </summary>
  private void OnEnable()
  {
    SwitchState(NPCState.Patrol);
  }

  /// <summary>
  /// Update is called every frame, if the MonoBehaviour is enabled.
  /// </summary>
  private void Update()
  {
    faceDir = new Vector3(-transform.localScale.x, 0, 0);
    curState.LogicUpdate();
    TimeCounter();
  }

  /// <summary>
  /// This function is called every fixed framerate frame, if the MonoBehaviour is enabled.
  /// </summary>
  private void FixedUpdate()
  {
    Move();
    curState.PhysicsUpdate();
  }

  /// <summary>
  /// This function is called when the behaviour becomes disabled or inactive.
  /// </summary>
  private void OnDisable()
  {
    curState.OnExit();
  }
  #endregion

  public virtual void Move()
  {
    if (
      !anim.GetCurrentAnimatorStateInfo(0).IsName("PreMove") &&
      !anim.GetCurrentAnimatorStateInfo(0).IsName("Recover") &&
       !isHurt && !isDead && !isWait)
      rb.velocity = new Vector2(curSpeed * faceDir.x * Time.deltaTime, rb.velocity.y);
  }

  /// <summary>
  /// idle 等待计数器
  /// </summary>
  public void TimeCounter()
  {
    if (isWait)
    {
      waitTimeCounter -= Time.deltaTime;
      if (waitTimeCounter <= 0)
      {
        isWait = false;
        waitTimeCounter = waitTime;
        // 翻转 轻易不用flip翻转 flip只能翻转图片，而不是翻转游戏对象，比如攻击的区域就不会跟着一起翻转
        transform.localScale = new Vector3(faceDir.x, 1, 1);
      }
    }

    // 如果没发现玩家，则倒计时--
    // 如果发现了玩家，则重置倒计时
    if (!FoundPlayer() && lostTimeCounter > 0)
    {
      lostTimeCounter -= Time.deltaTime;
    }
    else if (FoundPlayer())
    {
      lostTimeCounter = lostTime;
      isWait = false; // 处理： 野猪在wait的时候发现了玩家 应该立即取消wait状态
    }

  }

  public bool FoundPlayer()
  {
    return Physics2D.BoxCast(transform.position + new Vector3(centerOffset.x * faceDir.x, centerOffset.y), checkSize, 0, faceDir, checkDistance, attackLayer);
  }

  // 切换状态
  public void SwitchState(NPCState state)
  {

    curState?.OnExit();

    curState = state switch
    {
      NPCState.Patrol => patrolState,
      NPCState.Chase => chaseState,
      NPCState.Skill => skillState,
      _ => null
    };

    curState.OnEnter(this);
  }

  #region 事件执行方法
  public void OnTakeDamage(Transform attackerTrans)
  {
    attacker = attackerTrans;
    // 转身
    // 如果玩家在怪物右侧
    // enemy 贴图默认朝左，所以-1就变成朝右了
    if (attackerTrans.position.x > transform.position.x)
      transform.localScale = new Vector3(-1, 1, 1);
    if (attackerTrans.position.x < transform.position.x)
      transform.localScale = new Vector3(1, 1, 1);

    isHurt = true;
    anim.SetTrigger("hurt");
    // 计算击退方向 如果是飞行类敌人，考虑增加y轴的击退
    Vector2 repelDir = new Vector2(transform.position.x - attackerTrans.position.x, 0).normalized;
    rb.velocity = new Vector2(0, rb.velocity.y);
    StartCoroutine(OnHurt(repelDir));
  }

  /// 协程 
  private IEnumerator OnHurt(Vector2 dir)
  {
    rb.AddForce(dir * hurtForce, ForceMode2D.Impulse);
    yield return new WaitForSeconds(0.15f);
    isHurt = false;
  }

  public void OnDie()
  {
    // 将死亡物体放到ignore Raycase层，在edit -> project settings里面，取消player和这一层的碰撞关系
    gameObject.layer = 2;
    anim.SetBool("dead", true);
    isDead = true;
  }

  // 死亡动画播放结束后 销毁游戏对象
  public void DestroyAffterAnimation()
  {
    Destroy(this.gameObject);
  }
  #endregion

  private void OnDrawGizmosSelected()
  {
    Gizmos.color = Color.yellow;
    Gizmos.DrawWireSphere(transform.position + new Vector3(centerOffset.x * faceDir.x, centerOffset.y) + new Vector3(checkDistance * faceDir.x, 0), 0.4f);

    // Gizmos.DrawWireSphere(new Vector3(
    //   transform.position.x + (centerOffset.x + checkDistance) * faceDir.x,
    //   transform.position.y + centerOffset.y
    // ), 0.4f);

  }
}
